
package demo.model



import net.liftweb.mapper._
import net.liftweb._
import util._
import scala.math.BigDecimal
import net.liftweb.util.FieldError
import net.liftweb.http._
import java.math.MathContext
import net.liftweb.common.{Box,Full,Empty,Failure,ParamFailure}
import net.liftweb.json._
import net.liftweb.http.rest._
import net.liftweb.mapper.By



/**
 * define a Compound data Model using Mapper
 *
 *
 * author@narendra
 */

class Compound extends LongKeyedMapper[Compound] with IdPK {


  def getSingleton = Compound


  object compoundName extends MappedString(this,200)
  object inchiKey extends MappedString(this,100)
  object retentionTime extends MappedDecimal(this,MathContext.DECIMAL64,5)

  /**
   * define one-to-Many relation between method and compounds, respectively.
   */

  object method extends MappedLongForeignKey(this,Method) {
    override def validSelectValues = Full(Method.findAll.map(c =>(c.id.is,c.name.is)))
  }


}

/**
 * case class of Compound for Rest APi response
 * @param compoundName
 *
 */
case class CompoundAsJson(compoundName:String,inchiKey:String,retentionTime:BigDecimal)
{
  implicit val formats  = DefaultFormats
  def json = Extraction.decompose(this)
}


object Compound extends Compound with LongKeyedMetaMapper[Compound] {

  /**
   *  UniqueIndex Index
   * Method and Inchikey as Combined Key
   * one method can hold only one uniqe inchikey
   */
  override def dbIndexes = UniqueIndex(method, inchiKey) :: super.dbIndexes
  /**
   *
   * define database table name  for Compound
   */




  /**
   * converting Compound instance into json
   * @param in
   * @return
   */
  def encodeAsJson(in: Compound): JsonAST.JObject = encodeAsJSON_!(in)

  /**
   * converting json into Compound instance
   * @param json
   * @return
   */
  def buildFromJson(json: JsonAST.JObject,markFieldsAsDirty: Boolean): Compound = decodeFromJSON_!(json,markFieldsAsDirty)

  def updateFromJSON(compound: Compound, json: JsonAST.JObject): Compound =
    updateFromJSON_!(compound, json)
  /**
   * order of fields
   * @return
   */

  override def fieldOrder = List(compoundName,inchiKey,retentionTime)

  /**
   * send list of all compounds
   */
  private var compounds: List[JValue]  = Nil
  val list:List[Compound]  = Compound.findAll
  list.foreach{ e =>
  //updateListeners(e)
    compounds  ::= CompoundAsJson(e.compoundName,e.inchiKey,e.retentionTime).json
    //  methods ::=  encodeAsJson(e)
  }

  /**
   *
   * get all compounds in a sequence
   */

  def  seqCompounds : List[JValue] = compounds


  /**
   * add New Method
   *
   */
  def add(json: JsonAST.JObject): JsonAST.JObject = {

    val compound:Compound = buildFromJson(json, true)
    compound.validate match{
      case Nil =>{ compound.saveMe()
        json  }
      case errors:List[FieldError] => json
    }
  }

  /**
   * search by compound  name
   *
   */
  def search(str: String): List[JValue] = {
    var searchJson:List[JValue] =Nil
    val strLC = str.toLowerCase()
    var searchList:List[Compound]= Compound.findAll(By(Compound.compoundName, strLC))
    searchList.foreach{ e =>
      searchJson  ::= CompoundAsJson(e.compoundName,e.inchiKey,e.retentionTime).json
    }
    searchJson
  }

  /**
   * list of compounds for  Method
   */

  def searchByMethod(str: String): List[JValue] = {
    var searchJson:List[JValue] =Nil
    val strLC = str.toLowerCase()
    val byMethod:List[Method] = Method.findAll(By(Method.name,strLC))
    var searchList:List[Compound]= Compound.findAll(By(Compound.method, byMethod(0).id))
    searchList.foreach{ e =>
      searchJson  ::= CompoundAsJson(e.compoundName,e.inchiKey,e.retentionTime).json
    }
    searchJson
  }

}

